package dormouse.fx;

import java.net.URISyntaxException;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.log4j.Logger;

import dormouse.vfs.PathUtil;
import dormouse.vfs.RootFactory;
import dormouse.vfs.RootNames;
import dormouse.vfs.event.FileSelectionEventMixin;
import dormouse.vfs.event.IFileSelectionEvent;
import dormouse.vfs.event.IFileSelectionListener;
import dormouse.vfs.event.ILocationChangeListener;
import dormouse.vfs.event.LocationChangeEvent;
import dormouse.vfs.event.LocationChangeEventMixin;
import dormouse.vfs.metadata.IMetadataViewer;
import dormouse.vfs.ui.renderers.FileListRendererFactory;
import dormouse.vfs.ui.renderers.FileRendererFactory;
import dormouse.vfs.ui.renderers.IFileListRenderer;
import dormouse.vfs.ui.renderers.IFileRenderer;

/**
 * This is the primary controller for the Dormouse application.
 */
public class DormouseController implements Initializable, IFileSelectionListener {

	/** Class logger. */
	private static final Logger log = Logger
			.getLogger(DormouseController.class);

	@FXML
	private Label appLabel;

	@FXML
	private Button backBtn;

	@FXML
	private VBox bookmarkPanel;

	@FXML
	private Label bookmarksLabel;

	@FXML
	private Label desktopLabel;

	@FXML
	private Label docLabel;

	@FXML
	private Label facebookLabel;

	@FXML
	private Label feedLabel;

	@FXML
	private ChoiceBox<IFileListRenderer> fileViewChoice;

	@FXML
	private Button fwdBtn;

	@FXML
	private Label googlePlusLabel;

	@FXML
	private Label homeLabel;

	@FXML
	private Label movieLabel;

	@FXML
	private Label newsLabel;

	@FXML
	private Label pictLabel;

	@FXML
	private TextField searchFld;

	@FXML
	private Label statusLabel;

	@FXML
	private Label twitterLabel;

	@FXML
	private TextField locationFld;

	@FXML
	private BorderPane container;

	/** The current file list viewer. */
	private IFileListRenderer<Node> fileListViewer;
	
	private IFileRenderer<Node> fileMetadataViewer;

	/** The current metadata viewer. */
	private IMetadataViewer<Node> metadataViewer;

	/** This mixin provides support for location change events. */
	private LocationChangeEventMixin fileListEventMixin = new LocationChangeEventMixin();

	/** This mixin provides support for file selection events. */
	private FileSelectionEventMixin fileEventMixin = new FileSelectionEventMixin();

	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		fileViewChoice = new ChoiceBox<IFileListRenderer>();

		ObservableList<IFileListRenderer> viewerList = FXCollections
				.observableArrayList(FileListRendererFactory.getRenderers());
		fileViewChoice.setItems(viewerList);
		setFileListViewer(FileListRendererFactory.getDefaultInstance());

		locationFld.textProperty().addListener(new ChangeListener<String>() {

			@Override
			public void changed(ObservableValue<? extends String> arg0,
					String oldValue, String newValue) {

				FileObject old = null;

				if (oldValue != null && !oldValue.equals("")) {
					try {
						old = PathUtil.resolveFile(oldValue);
					} catch (FileSystemException e) {
						log.error(e.getMessage(), e);
					}
				}

				FileObject nu = null;
				if (newValue != null && !newValue.equals("")) {
					try {
						nu = PathUtil.resolveFile(newValue);
					} catch (FileSystemException e) {
						log.error(e.getMessage(), e);
					}
				}

				fileListEventMixin.notify(new LocationChangeEvent(old, nu));

			}

		});

	}

	/**
	 * This method sets the text of the status label.
	 * 
	 * @param value
	 *            the new message for the status label.
	 */
	public void setStatus(String value) {
		statusLabel.setText(value);
	}

	/**
	 * This method adds a location change listener.
	 * 
	 * @param listener
	 *            the listener to be added.
	 */
	public void addLocationChangeListener(ILocationChangeListener listener) {
		fileListEventMixin.addListener(listener);
	}

	/**
	 * This method removes a location change listener.
	 * 
	 * @param listener
	 */
	public void removeLocationChangeListener(ILocationChangeListener listener) {
		fileListEventMixin.removeListener(listener);
	}

	/**
	 * This method sets the currently selected file list renderer.
	 * 
	 * @param view
	 */
	public void setFileListViewer(IFileListRenderer<Node> view) {
		fileListViewer = view;
		container.setCenter(view.getComponent());
		container.layout();
		addLocationChangeListener(fileListViewer);
		fileListViewer.addFileSelectionListener(this);
		log.debug("renderer set");
	}

	/**
	 * This method sets the currently selected file list renderer.
	 */
	public void clearFileListViewer() {
		removeLocationChangeListener(fileListViewer);
		fileListViewer = null;
	}

	public void setMetadataViewer(IMetadataViewer<Node> viewer) {
		metadataViewer = viewer;
		container.setRight(viewer.getComponent());
		fileEventMixin.addFileSelectionListener(viewer);
	}

	public void clearMetadataViewer() {
		metadataViewer = null;
	}

	public void appsAction() {
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.APPLICATIONS));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}

	public void fwdAction() {
		//TODO implement me
	}

	public void backAction() {
		//TODO implement me
	}

	public void bookmarksAction() {
		//TODO implement me
	}
	
	public void downloadsAction(){
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.DOWNLOADS));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}

	public void docsAction() {
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.DOCUMENTS));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}
	
	public void musicAction(){
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.MUSIC));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}

	public void moviesAction() {
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.MOVIES));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}

	public void desktopAction() {
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.DESKTOP));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}

	public void homeAction() {

		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.HOME));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}

	}
	
	public void photosAction(){
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.PHOTOS));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}
	
	public void newsAction(){
		
	}
	
	public void facebookAction(){
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.FACEBOOK));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}
	
	public void twitterAction(){
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.TWITTER));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}
	
	public void googleAction(){
		try {
			locationFld.setText(RootFactory.getRootPath(RootNames.GOOGLE_PLUS));
		} catch (FileSystemException | URISyntaxException e) {
			log.error(e.getMessage(), e);
		}
	}

	@Override
	public void fileSelected(IFileSelectionEvent event) {
		FileObject file = event.getSelectedFile();
		
		if (file != null){
			fileMetadataViewer = FileRendererFactory.getInstance(file);
			container.setRight(fileMetadataViewer.getComponent());
		}
		
	}

}
